
class Person {
    // 声明构造器当中的属性的类型
    name: string;
    age: number;
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    //原型对象上的方法
    jump(a: string): string {
        return a + this.name
    }
    // class类自身上的方法
    static run(x: number): number {
        return x
    }
}
let tom = new Person('tom', 18);
console.log(tom);
//面试题：如何调试原型对象上的方法  答：使用实例对象可以通过隐式原型链访问到原型对象上的方法
console.log(tom.jump('ss'));

// class类或者构造函数自身上的方法如何调用   对象自身的方法 obj.xxx  obj['xxx']
console.log(Person.run(4));


export {
    tom,
}

//使用接口规定类的数据对象
interface Anima {
    sound(str:string): string,
    weight(num:number): number,
}

interface Anima1 {
    name(str:string):string
}

class Catt implements Anima , Anima1{  //Catt 根据 Anima 和 Anima1的接口规则创建
    sound(a:string): string {           // 一个类可以使用多个接口进行规定
        return a
    }
    weight(num:number): number {
        return num
    }
    name(str:string):string{
        return str
    }
}


let qqq = new Catt();
console.log(qqq);

console.log(qqq.sound('啥啥啥'));
console.log(qqq.sound('颠三倒四'))
// 接口可以继承

//可合并接口
interface Q1 {
    sound(str:string):string,
}

interface Q2 {
    run(num:number):number,
}

interface QQ extends Q1 ,Q2 {

}
//接口可继承接口
class DQ implements QQ{
    sound(str: string): string {
        return str
    }
    run(num: number): number {
        return num
    }
}

let DQQ = new DQ()
console.log(DQQ.sound('w啥啥啥'));
console.log(DQQ.run(2222));


// class类继承

class Students extends Person{
    sex:string;
    // 进行规定构造器当中参数的数据类型
    constructor(name:string,age:number,sex:string){
        super(name,age);
        this.sex = sex;
    }
    jump(a: string): string {
        return super.jump(a);
    }
}

let qw = new Students('sss',23,'sdas');
console.log(qw.jump('DSADS'))


// 修饰符
/* 
public 默认值哪里都有访问
private 私有的 只有内部可以访问
protected 受保护的 只有内部和子类可以访问
readonly 只读在属性声明或者构造函数里进行初始化

*/
class Dog {
    public name : string;
    private price:string;
    protected pages:number;
    readonly hobby:string;
    constructor(name:string,price:string,pages:number,hobby:string){
        this.name = name;
        this.price = price;
        this.pages = pages;
        this.hobby = hobby;
    }
    DogName():void{
        //class内部
        console.log(this.price);
        console.log(this.pages);
        //在内部访问
        // return this.name;
    }
}

let bomei = new Dog('bomei','400块钱',123,'睡觉');
    console.log(bomei.name);
    console.log(bomei);
    console.log(bomei.DogName())
    //不可在外部访问
    // console.log(bomei.price);
    // console.log(bomei.pages);
    bomei.DogName();
//protected内部和子类中可以访问 外部不能访问
class Demu extends Dog{
    constructor(name:string,price:string,pages:number,hobby:string){
        super(name,price,pages,hobby);
    }
    test():void{
        console.log(this.name);
        //   console.log(this.price);
        console.log(this.pages);
    }
}

let xiaoDemu = new Demu('xiaoDemu','3900块钱',1000,'睡觉');
console.log(xiaoDemu);
xiaoDemu.test();
console.log(bomei);
console.log(xiaoDemu.test());
console.log(xiaoDemu.hobby);
console.log(bomei.hobby);

//简写 参数属性 public
class Xiaoli{
    // name:string  pulic省略了构造器中的属性类型规定
    // age:number
    constructor(public name:string, public age:number){
        this.name = name;
        this.age = age;
    }
}
let lili = new Xiaoli('sdas',22);
console.log(lili);

// 存取器
// get set
//get 读取值
 // 当值更改时就会触发set  触发set之后，获取新值，可以根据逻辑进行操作
class Zl{
    name:string = '志龙';
    hobby:string = '打游戏'
    // constructor (name:string,hobby:string){  //修改
    //     this.name = name;
    //     this.hobby = hobby;
    // }
    get zlh():string{
        return this.name + this.hobby
    }
    set zlh(value){
        console.log(value);
    }
}
// let Xzl = new Zl("老刘","吃饭");
let Xzl = new Zl();
console.log(Xzl.zlh);
Xzl.zlh = '吃不饱';

// 抽象类
// 抽象类做为其它派生类的基类使用(当父类的),不能创建实例对象, 只有实现类才能创建实例可以包含未实现的抽象方法
//abstract 关键字是用于定义抽象类和在抽象类内部定义抽象方法
abstract class Parent{
    abstract run()
    abstract jump();
}

class Son extends Parent{
    run() { //父类当中有什么,子类里必须有
        console.log('子类当中的值')
    }
    jump() {
        console.log('子类第二个值')
    }
}
let Day = new Son();
Day.run();
Day.jump();

// 多态
// 父类型的引用指向了子类型的对象，不同类型的对象针对相同的方法，产生了不同的行为

class Asa{
    name:string;
    age:number;
    constructor(name:string,age:number){
        this.name = name;
        this.age = age;
    }
    jump(height:number):string{
        return `${this.name}跳${height}`
    }
}
class Giao extends Asa{
    constructor(name:string,age:number){
        super(name,age);
    }
    jump(height: number): string { //jump 在其中继承父类原型对象上的jump  super.jump()
        return super.jump(height);
    }
}

class Giao2 extends Asa{
    constructor(name:string,age:number){
        super(name,age);
    }
    jump(height: number): string { //jump 在其中继承父类原型对象上的jump  super.jump()
        return super.jump(height);
    }
}

let Aaa:Asa = new Giao('aaa',33);
console.log(Aaa);
console.log(Aaa.jump(30)) ;

let sui:Asa = new Giao2('sui',22);
console.log(sui);
console.log(sui.jump(22));

// 不同的类型的对象针对相同的方法，产生了不同的行为  现象称为多态





